package com.wu.framework.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 登录用户信息工具类，通过request header传递
 *
 * @author 黄珺
 * @date 2019-09-19
 */
public class SecurityContextUtils {

    public static final String KEY_NAME_USERNAME = "username";
    public static final String KEY_NAME_USER_ID = "userId";
    public static final String KEY_NAME_USER_CLIENT_IP = "userClientIP";
    public static final String KEY_NAME_USER_TOKEN = "userToken";
    public static final String KEY_NAME_TENANT_ID = "tenantId";
    public static final String KEY_NAME_AUTHORITIES = "authorities";
    public static final String KEY_NAME_ROLE_IDS = "roleIds";
    public static final String KEY_NAME_DEPARTMENT_ID = "departmentId";
    public static final String KEY_NAME_POSITION_ID = "positionId";
    public static final String KEY_NAME_IS_ADMIN = "isAdmin";
    public static final String KEY_NAME_DATA_PERMISSION = "dataPermission";

    public static final String USER_TOKEN_APP_KEY = "SYSTEM";

    public static ArrayList<String> AUTH_HEADER_NAME_LIST = new ArrayList<>(10);

    static {
        Collections.addAll(AUTH_HEADER_NAME_LIST, KEY_NAME_USERNAME, KEY_NAME_USER_ID, KEY_NAME_USER_CLIENT_IP, KEY_NAME_USER_TOKEN, KEY_NAME_ROLE_IDS, KEY_NAME_DEPARTMENT_ID, KEY_NAME_POSITION_ID, KEY_NAME_IS_ADMIN, KEY_NAME_DATA_PERMISSION);
    }

    private final static ObjectMapper objectMapper=new ObjectMapper();

    /**
     * 转发session中用户信息至消息头中
     *
     * @param session       session
     * @param zuulHeaderMap zuul消息头键值集合
     */
    public static void relayToZuulHeader(HttpSession session, Map<String, String> zuulHeaderMap) {
        try {
            // 使用url编码解决中文乱码
            zuulHeaderMap.put(KEY_NAME_USERNAME,
                    URLEncoder.encode(String.valueOf(session.getAttribute(KEY_NAME_USERNAME)), StandardCharsets.UTF_8.name()));
        } catch (UnsupportedEncodingException ignore) {

        }
        zuulHeaderMap.put(KEY_NAME_USER_ID, String.valueOf(session.getAttribute(KEY_NAME_USER_ID)));
        zuulHeaderMap.put(KEY_NAME_USER_TOKEN, String.valueOf(session.getAttribute(KEY_NAME_USER_TOKEN)));
        if (session.getAttribute(KEY_NAME_USER_CLIENT_IP) != null) {
            zuulHeaderMap.put(KEY_NAME_USER_CLIENT_IP, String.valueOf(session.getAttribute(KEY_NAME_USER_CLIENT_IP)));
        }
        if (session.getAttribute(KEY_NAME_DEPARTMENT_ID) != null) {
            zuulHeaderMap.put(KEY_NAME_DEPARTMENT_ID, String.valueOf(session.getAttribute(KEY_NAME_DEPARTMENT_ID)));
        }
        if (session.getAttribute(KEY_NAME_POSITION_ID) != null) {
            zuulHeaderMap.put(KEY_NAME_POSITION_ID, String.valueOf(session.getAttribute(KEY_NAME_POSITION_ID)));
        }
        zuulHeaderMap.put(KEY_NAME_IS_ADMIN, String.valueOf(session.getAttribute(KEY_NAME_IS_ADMIN)));

//        zuulHeaderMap.put(KEY_NAME_ROLE_IDS, objectMapper.writeValueAsString((session.getAttribute(KEY_NAME_ROLE_IDS))));
//        zuulHeaderMap.put(KEY_NAME_DATA_PERMISSION, objectMapper.writeValueAsString(session.getAttribute(KEY_NAME_DATA_PERMISSION)));
    }

    /**
     * 获取当前线程的request对象
     *
     * @return HttpServletRequest
     * @throws IllegalStateException 在非web线程中调用该方法
     */
    private static HttpServletRequest getRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            throw new IllegalStateException("当前线程中不存在Request上下文");
        }
        return requestAttributes.getRequest();
    }

    /**
     * 获取当前用户名称
     *
     * @return 用户名称
     */
    public static String getCurrentUsername() {
        HttpServletRequest request = getRequest();
        String encodeName = request.getHeader(KEY_NAME_USERNAME);
        if (encodeName != null) {
            try {
                return URLDecoder.decode(encodeName, StandardCharsets.UTF_8.name());
            } catch (UnsupportedEncodingException ignored) {

            }
        } else {
            return (String) Optional.ofNullable(request.getSession(false)).map(session -> session.getAttribute(KEY_NAME_USERNAME)).orElse(null);
        }

        return null;
    }

    /**
     * 获取当前用户id
     *
     * @return 用户id
     */
    public static Long getCurrentUserId() {
        HttpServletRequest request = getRequest();
        String userId = request.getHeader(KEY_NAME_USER_ID);
        if (userId != null) {
            return Long.valueOf(userId);
        }
        return (Long) Optional.ofNullable(request.getSession(false)).map(session -> session.getAttribute(KEY_NAME_USER_ID)).orElse(null);
    }

    /**
     * 获取当前用户客户端IP
     *
     * @return 用户客户端IP
     */
    public static String getCurrentUserClientIP() {
        HttpServletRequest request = getRequest();
        String clientIP = request.getHeader(KEY_NAME_USER_CLIENT_IP);
        if (clientIP == null) {
            clientIP = (String) Optional.ofNullable(request.getSession(false)).map(session -> session.getAttribute(KEY_NAME_USER_CLIENT_IP)).orElse(null);
        }
        return clientIP;
    }

    /**
     * 获取当前用户部门id
     *
     * @return 用户部门id
     */
    public static Long getCurrentUserDepartmentId() {
        HttpServletRequest request = getRequest();
        String departmentId = request.getHeader(KEY_NAME_DEPARTMENT_ID);
        if (departmentId != null) {
            return Long.valueOf(departmentId);
        }
        return (Long) Optional.ofNullable(request.getSession(false)).map(session -> session.getAttribute(KEY_NAME_DEPARTMENT_ID)).orElse(null);
    }

    /**
     * 获取当前用户职位id
     *
     * @return 用户职位id
     */
    public static Long getCurrentUserPositionId() {
        HttpServletRequest request = getRequest();
        String positionId = request.getHeader(KEY_NAME_POSITION_ID);
        if (positionId != null) {
            return Long.valueOf(positionId);
        }
        return (Long) Optional.ofNullable(request.getSession(false)).map(session -> session.getAttribute(KEY_NAME_POSITION_ID)).orElse(null);
    }

    /**
     * 获取当前用户访问token
     *
     * @return 用户访问token
     */
    public static String getCurrentUserToken() {
        HttpServletRequest request = getRequest();
        String userToken = request.getHeader(KEY_NAME_USER_TOKEN);
        if (userToken == null) {
            userToken = (String) Optional.ofNullable(request.getSession(false)).map(session -> session.getAttribute(KEY_NAME_USER_TOKEN)).orElse(null);
        }
        return userToken;
    }

    /**
     * 获取当前用户角色id列表
     *
     * @return 角色id列表
     */
    public static List<Long> getCurrentUserRoles() throws JsonProcessingException {
        HttpServletRequest request = getRequest();
        String userRoles = request.getHeader(KEY_NAME_ROLE_IDS);
        if (userRoles != null) {
            return objectMapper.readValue(userRoles, new TypeReference<List<Long>>() {
            });
        }
        return (List<Long>) Optional.ofNullable(request.getSession(false)).map(session -> session.getAttribute(KEY_NAME_ROLE_IDS)).orElse(null);
    }

    /**
     * 获取当前用户是否拥有管理员角色
     *
     * @return 是否管理员角色
     */
    public static Boolean isCurrentUserAdmin() {
        HttpServletRequest request = getRequest();
        String isAdmin = request.getHeader(KEY_NAME_IS_ADMIN);
        if (isAdmin != null) {
            return Boolean.valueOf(isAdmin);
        }
        return (Boolean) Optional.ofNullable(request.getSession(false)).map(session -> session.getAttribute(KEY_NAME_IS_ADMIN)).orElse(null);
    }

    /**
     * 获取当前用户指定数据表数据权限，多个以‘,’分隔
     *
     * @return 数据权限字符串
     */
    public static String getCurrentUserDataPermissionCode(String tableName) throws JsonProcessingException {
        return getCurrentUserDataPermissionMap().get(tableName);
    }

    /**
     * 获取当前用户数据权限集合
     *
     * @return 数据权限集合，key：tableName，value：permissionCode，以‘,’分隔
     */
    private static Map<String, String> getCurrentUserDataPermissionMap() throws JsonProcessingException {
        HttpServletRequest request = getRequest();
        String permissionMapJson = request.getHeader(KEY_NAME_DATA_PERMISSION);
        if (permissionMapJson != null) {
            return objectMapper.readValue(permissionMapJson, new TypeReference<Map<String, String>>() {
            });
        }
        return (Map<String, String>) Optional.ofNullable(request.getSession(false)).map(session -> session.getAttribute(KEY_NAME_DATA_PERMISSION)).orElse(null);
    }


    /**
     * description 获取当前用户 所在租户
     * @param
     * @return
     * @exception/throws
     * @author 吴佳伟
     * @date 2021/5/27 3:44 下午
     */
    public static String getCurrentUserTenantId() {
        HttpServletRequest request = getRequest();
        String tenantId = request.getHeader(KEY_NAME_TENANT_ID);
        if (tenantId == null) {
            tenantId = (String) Optional.ofNullable(request.getSession(false)).map(session -> session.getAttribute(KEY_NAME_TENANT_ID)).orElse(null);
        }
        return tenantId;
    }
}
